import { Injectable, Logger } from '@nestjs/common';
import { Keypair } from '@solana/web3.js';
import * as crypto from 'crypto';
import { Worker } from 'worker_threads';
import * as path from 'path';

export interface PrettyAddressConfig {
  prefix?: string;
  suffix?: string;
  caseSensitive?: boolean;
  threads?: number;
  maxAttempts?: number;
}

export interface PrettyAddressResult {
  publicKey: string;
  secretKey: number[];
  attempts: number;
  timeElapsed: number;
  difficulty: number;
}

@Injectable()
export class PrettyAddressService {
  private readonly logger = new Logger(PrettyAddressService.name);

  /**
   * 计算靓号难度
   */
  calculateDifficulty(prefix: string = '', suffix: string = '', caseSensitive: boolean = false): number {
    const prefixLength = prefix.length;
    const suffixLength = suffix.length;
    const totalLength = prefixLength + suffixLength;
    
    if (totalLength === 0) return 1;
    
    // Base58字符集大小
    const charset = caseSensitive ? 58 : 32; // 不区分大小写时减少字符集
    
    // 计算理论尝试次数
    const difficulty = Math.pow(charset, totalLength);
    
    return Math.floor(difficulty);
  }

  /**
   * 估算生成时间（秒）
   */
  estimateTime(difficulty: number, threadsCount: number = 1): number {
    // 假设每秒每线程可以生成约10000个地址
    const addressesPerSecondPerThread = 10000;
    const totalAddressesPerSecond = addressesPerSecondPerThread * threadsCount;
    
    // 预期需要尝试一半的可能性才能找到
    const expectedAttempts = difficulty / 2;
    
    return Math.ceil(expectedAttempts / totalAddressesPerSecond);
  }

  /**
   * 验证地址是否符合要求
   */
  private validateAddress(address: string, config: PrettyAddressConfig): boolean {
    const { prefix = '', suffix = '', caseSensitive = false } = config;
    
    if (!prefix && !suffix) return true;
    
    const targetAddress = caseSensitive ? address : address.toLowerCase();
    const targetPrefix = caseSensitive ? prefix : prefix.toLowerCase();
    const targetSuffix = caseSensitive ? suffix : suffix.toLowerCase();
    
    const hasValidPrefix = !prefix || targetAddress.startsWith(targetPrefix);
    const hasValidSuffix = !suffix || targetAddress.endsWith(targetSuffix);
    
    return hasValidPrefix && hasValidSuffix;
  }

  /**
   * 单线程生成靓号地址
   */
  private generatePrettyAddressSingleThread(config: PrettyAddressConfig): PrettyAddressResult | null {
    const startTime = Date.now();
    const maxAttempts = config.maxAttempts || 1000000;
    let attempts = 0;

    while (attempts < maxAttempts) {
      attempts++;
      
      const keypair = Keypair.generate();
      const address = keypair.publicKey.toString();
      
      if (this.validateAddress(address, config)) {
        const timeElapsed = Date.now() - startTime;
        const difficulty = this.calculateDifficulty(config.prefix, config.suffix, config.caseSensitive);
        
        return {
          publicKey: address,
          secretKey: Array.from(keypair.secretKey),
          attempts,
          timeElapsed,
          difficulty
        };
      }
      
      // 每1000次尝试检查一次时间，避免无限循环
      if (attempts % 1000 === 0) {
        const elapsed = Date.now() - startTime;
        if (elapsed > 300000) { // 5分钟超时
          this.logger.warn(`Pretty address generation timeout after ${attempts} attempts`);
          break;
        }
      }
    }
    
    return null;
  }

  /**
   * 多线程生成靓号地址
   */
  async generatePrettyAddressMultiThread(config: PrettyAddressConfig): Promise<PrettyAddressResult | null> {
    const threads = config.threads || 1;
    
    if (threads === 1) {
      return this.generatePrettyAddressSingleThread(config);
    }

    return new Promise((resolve, reject) => {
      const workers: Worker[] = [];
      let resolved = false;
      
      const cleanup = () => {
        workers.forEach(worker => worker.terminate());
      };

      for (let i = 0; i < threads; i++) {
        const worker = new Worker(`
          const { parentPort } = require('worker_threads');
          const { Keypair } = require('@solana/web3.js');
          
          const config = ${JSON.stringify(config)};
          const maxAttempts = Math.floor((config.maxAttempts || 1000000) / ${threads});
          let attempts = 0;
          let resolved = false;
          const startTime = Date.now();
          
          function validateAddress(address, config) {
            const { prefix = '', suffix = '', caseSensitive = false } = config;
            
            if (!prefix && !suffix) return true;
            
            const targetAddress = caseSensitive ? address : address.toLowerCase();
            const targetPrefix = caseSensitive ? prefix : prefix.toLowerCase();
            const targetSuffix = caseSensitive ? suffix : suffix.toLowerCase();
            
            const hasValidPrefix = !prefix || targetAddress.startsWith(targetPrefix);
            const hasValidSuffix = !suffix || targetAddress.endsWith(targetSuffix);
            
            return hasValidPrefix && hasValidSuffix;
          }
          
          while (attempts < maxAttempts && !resolved) {
            attempts++;
            
            const keypair = Keypair.generate();
            const address = keypair.publicKey.toString();
            
            if (validateAddress(address, config)) {
              const timeElapsed = Date.now() - startTime;
              parentPort.postMessage({
                success: true,
                result: {
                  publicKey: address,
                  secretKey: Array.from(keypair.secretKey),
                  attempts: attempts * ${threads}, // 估算总尝试次数
                  timeElapsed,
                  difficulty: ${this.calculateDifficulty(config.prefix, config.suffix, config.caseSensitive)}
                }
              });
              break;
            }
            
            if (attempts % 1000 === 0) {
              const elapsed = Date.now() - startTime;
              if (elapsed > 300000) break; // 5分钟超时
            }
          }
          
          if (attempts >= maxAttempts) {
            parentPort.postMessage({ success: false, attempts });
          }
        `, { eval: true });

        worker.on('message', (message) => {
          if (resolved) return;
          
          if (message.success) {
            resolved = true;
            cleanup();
            resolve(message.result);
          }
        });

        worker.on('error', (error) => {
          if (!resolved) {
            resolved = true;
            cleanup();
            reject(error);
          }
        });

        workers.push(worker);
      }

      // 设置总体超时
      setTimeout(() => {
        if (!resolved) {
          resolved = true;
          cleanup();
          resolve(null);
        }
      }, 300000); // 5分钟超时
    });
  }

  /**
   * 生成靓号地址
   */
  async generatePrettyAddress(config: PrettyAddressConfig): Promise<PrettyAddressResult | null> {
    this.logger.log(`Starting pretty address generation with config:`, config);
    
    const difficulty = this.calculateDifficulty(config.prefix, config.suffix, config.caseSensitive);
    const estimatedTime = this.estimateTime(difficulty, config.threads);
    
    this.logger.log(`Difficulty: ${difficulty}, Estimated time: ${estimatedTime}s`);
    
    // 如果难度太高，建议用户减少字符数
    if (difficulty > 1000000) {
      this.logger.warn(`High difficulty detected: ${difficulty}. Consider reducing prefix/suffix length.`);
    }
    
    const result = await this.generatePrettyAddressMultiThread(config);
    
    if (result) {
      this.logger.log(`Pretty address generated successfully: ${result.publicKey} in ${result.attempts} attempts (${result.timeElapsed}ms)`);
    } else {
      this.logger.warn(`Failed to generate pretty address with config:`, config);
    }
    
    return result;
  }

  /**
   * 批量生成靓号地址
   */
  async generateMultiplePrettyAddresses(config: PrettyAddressConfig, count: number = 1): Promise<PrettyAddressResult[]> {
    const results: PrettyAddressResult[] = [];
    
    for (let i = 0; i < count; i++) {
      this.logger.log(`Generating pretty address ${i + 1}/${count}`);
      
      const result = await this.generatePrettyAddress(config);
      if (result) {
        results.push(result);
      } else {
        this.logger.warn(`Failed to generate pretty address ${i + 1}/${count}`);
        break; // 如果一个失败了，停止生成
      }
    }
    
    return results;
  }

  /**
   * 验证靓号配置是否合理
   */
  validatePrettyConfig(config: PrettyAddressConfig): { valid: boolean; message?: string } {
    const { prefix = '', suffix = '', threads = 1 } = config;
    
    // 检查字符是否在Base58字符集中
    const base58Chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
    
    for (const char of prefix + suffix) {
      if (!base58Chars.includes(char)) {
        return {
          valid: false,
          message: `Invalid character '${char}' in prefix/suffix. Only Base58 characters are allowed.`
        };
      }
    }
    
    // 检查长度
    if (prefix.length + suffix.length > 8) {
      return {
        valid: false,
        message: 'Combined prefix and suffix length should not exceed 8 characters for reasonable generation time.'
      };
    }
    
    // 检查线程数
    if (threads < 1 || threads > 16) {
      return {
        valid: false,
        message: 'Thread count should be between 1 and 16.'
      };
    }
    
    // 检查难度
    const difficulty = this.calculateDifficulty(prefix, suffix, config.caseSensitive);
    if (difficulty > 10000000) {
      return {
        valid: false,
        message: `Difficulty too high (${difficulty}). Consider reducing prefix/suffix length.`
      };
    }
    
    return { valid: true };
  }
}
